package cn.com.zcode.core.cxf.client;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import org.apache.cxf.endpoint.Client;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;
import org.apache.log4j.Logger;

/**
 * 
 * @author zeng.jinqing
 * @date Apr 19, 2013
 */
public class WebServiceClientFactory {

	private static Map<String, Client> keyMap = new HashMap<String, Client>();
	private static final Logger logger = Logger.getLogger(WebServiceClientFactory.class);

	/**
	 * Create the instance of T from Wsdl.
	 * 
	 * @param zlass
	 * @param key
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> T getClient(Class<T> zlass, String wsdl) {
		JaxWsProxyFactoryBean bean = new JaxWsProxyFactoryBean();
		bean.setServiceClass(zlass);
		bean.setAddress(wsdl);
		T client = (T) bean.create();
		return client;
	}

	/**
	 * Invoke remote web service method by wsdl<br/>
	 * This method will create an dynamic client from the wsdl.
	 * 
	 * @param wsdl
	 * @param method
	 * @param parm
	 * @return
	 * @throws Exception
	 */
	public static ObjectProxy invoke(String wsdl, String method, Object... parm) throws WebServiceClientException {
		logger.info("==================================================================");
		logger.info("WSDL:" + wsdl);
		logger.info("Method:" + method + " \tParms:" + (parm == null ? null : Arrays.toString(parm)));
		logger.info("==================================================================");
		Client client = null;
		if (wsdl != null && !(wsdl = wsdl.trim()).isEmpty()) {
			wsdl = wsdl.endsWith("?wsdl") ? wsdl : wsdl + "?wsdl";
			client = keyMap.get(wsdl);
			if (client == null) {
				try {
					JaxWsDynamicClientFactory clientFactory = JaxWsDynamicClientFactory.newInstance();

					client = clientFactory.createClient(wsdl);
				} catch (Exception e) {
					e.printStackTrace();
					throw new WebServiceClientException("Created web service client fail,wsdl: " + wsdl, e);
				}
				if (client != null) {
					keyMap.put(wsdl, client);
				}
			}
		}

		if (client != null) {
			try {
				Object[] result = null;
				if (parm == null) {
					result = client.invoke(method);
				} else {
					for (int i = 0; i < parm.length; i++) {
						Object obj = parm[i];
						parm[i] = ConvertUtil.parse2WsObject(obj);
					}
					result = client.invoke(method, parm);
				}
				ObjectProxy objprox = null;
				if (result != null) {
					objprox = new ObjectProxy(result[0]);
				}
				logger.info("==================================================================");
				logger.info("Response of web service:" + objprox);
				logger.info("==================================================================");
				return objprox;
			} catch (Exception e) {
				e.printStackTrace();
				throw new WebServiceClientException("Fail to invoke webservice", e);

			}
		} else {
			throw new WebServiceClientException("Fail to create webservice client");
		}

	}
}
